#include "Event_Test.h"

#include "misc/Event.h"
#include "Poco/Exception.h"
#include <iostream>
/*********************************************************/
std::string EventTest::name()
{
	return("Event");
}
/*********************************************************/
bool EventTest::runUnitTests()
{
	bool result = true;

	if ( !createEventTest() ) result = false;
	if ( !eventUniqueTest() ) result = false;
	if ( !doubleEventTest() ) result = false;
	if ( !lockUnlockTest() ) result = false;
	if ( !maxSetTest() ) result = false;
	if ( !resetEventTest() ) result = false;

	return( result ) ;
}
/*********************************************************/
bool EventTest::resetEventTest()
{
	std::cout << "Running: resetEventTest()";
	std::cout.flush();
	Event* e = Event::Instance("TEST");

	// Test the reset with less then SEM_MAX flags
	for (int i=0; i<SEM_MAX; i++ ) {
		e->set();
	}
	e->reset();

	if ( e->tryWait(50) ) {
		std::cout << "... Failed!" << std::endl;
		return( false );
	}
	
	// Test reset with more sets then SEM_MAX
	for (int i=0; i<SEM_MAX+1; i++ ) {
		e->set();
	}
	e->reset();

	if ( e->tryWait(50) ) {
		std::cout << "... Failed!" << std::endl;
		return( false );
	}

	std::cout << "... success!" << std::endl;
	return( true );
}
/*********************************************************/
bool EventTest::createEventTest()
{
	std::cout << "Running: createEventTest()";
	Event* e = Event::Instance("TEST");

	if ( e->getName() == "TEST" ) {
		std::cout << "... success!" << std::endl;
		return( true );
	} else {
		std::cout << "... Failed!" << std::endl;
		return( false );
	}
}
/*********************************************************/
bool EventTest::eventUniqueTest()
{
	std::cout << "Running: eventUniqueTest()";
	Event* e1 = Event::Instance("TEST");
	Event* e2 = Event::Instance("TEST");

	if ( e1 == e2 ) {
		std::cout << "... success!" << std::endl;
		return( true );
	} else {
		std::cout << "... Failed!" << std::endl;
		return( false );
	}
}
/*********************************************************/
bool EventTest::doubleEventTest()
{
	std::cout << "Running: doubleEventTest()";
	Event* e1 = Event::Instance("TEST");
	Event* e2 = Event::Instance("TEST2");
	Event* e3 = Event::Instance("TEST");

	if (( e1 == e3 ) && ( e1 != e2 )){
		std::cout << "... success!" << std::endl;
		return( true );
	} else {
		std::cout << "... Failed!" << std::endl;
		return( false );
	}
}
/*********************************************************/
bool EventTest::lockUnlockTest()
{
	try {
		std::cout << "Running: lockUnlockTest()";
		Event* e = Event::Instance("TEST");

		e->set();
		e->wait();

		std::cout << "... success!" << std::endl;
		return( true );
	} catch(Poco::Exception& e) {
		std::cout << "... Exception caught: " << e.displayText() << "... Failed!" << std::endl;
		return( false);
	} catch(...) {
		std::cout << "... Unknown exception caught... Failed!" << std::endl;
		return( false );
	}
}
/*********************************************************/
bool EventTest::maxSetTest()
{
	try {
		std::cout << "Running: maxSetTest()";
		Event* e = Event::Instance("TEST");
		
		// Set the event up to it's max settings for the semaphore + 1
		for ( int i = 0; i<SEM_MAX+1; i++ ) {
			e->set();
		}

		// We wait for the same event SEM_MAX + 1 times
		for ( int i = 0; i<SEM_MAX+1; i++ ) {
			e->wait();
		}

		// Check if we can unlock the semaphore once more
		if ( e->tryWait(250) ) {		// wait 250 ms
			std::cout << "... Failed!" << std::endl;
			return( false );
		}

		// if all went well we got unlocked otherwise we are nog stuck in the test
		// or poco threw an exception
		std::cout << "... success!" << std::endl;
		return( true );
	
	} catch(Poco::Exception& e) {
		std::cout << "... Exception caught: " << e.displayText() << "... Failed!" << std::endl;
		return( false);
	} catch(...) {
		std::cout << "... Unknown exception caught... Failed!" << std::endl;
		return( false );
	}
}
